package Persistencia;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import Dominio.Articulo;
import Dominio.Cliente;
import Dominio.Devolucion;
import Dominio.Pago;
import Dominio.Reserva;
import Dominio.Servicio;
import Dominio.Sesion;
import Dominio.Socio;
import Dominio.Usuario;
import Dominio.Venta;


public class AgenteBD {
	
	//------- ARTICULOS ----------
	
	private static HibernateUtil hibernateUtil;
	private static Session session;
	
	static{
		try{
			hibernateUtil = new HibernateUtil();
			session = hibernateUtil.getSession();
		}catch(Exception e){
			System.err.println("ERROR al acceder a la base de datos");
			e.printStackTrace();
		}
	}
	
	public static List<Articulo> consultarArticulosBD(){
		List<Articulo> articulos=null;
		Criteria crit = session.createCriteria(Articulo.class);
	    articulos = crit.list();
		return articulos;
	}
	
	public static Articulo consultarArticuloBD(int re){
		Articulo a = null;
		try {
			a=(Articulo) session.load(Articulo.class, re);
		} catch (Exception e) {
			System.err.println("ERROR al consultar articulo");
			e.printStackTrace();
		}
		return a;
	}
	public static int crearArticuloBD(Articulo a){
		int res=0;
		try {
		    session.save(a);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al crear articulo");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int modificarArticuloBD(Articulo a){
		int res=0;
		try {
		    session.update(a);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al modificar articulo");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	
	public static int borrarArticuloBD(Articulo a){
		int res=0;
		try {
		    session.delete(a);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al borrar articulo");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	
	//----- CLIENTES -------
	
	//devuelve todos los clientes de la BD
	public static List<Cliente> consultarClientesBD(){
		List<Cliente> clientes=null;
		Criteria crit = session.createCriteria(Cliente.class);
	    clientes = crit.list();
		return clientes;
	}
	
	public static List<Cliente> consultarClientesSociosBD() {
		List<Cliente> lc=null;
		
	    Query query = session.createQuery("from Cliente where esSocio = 1");
	    lc = query.list();
		return lc;
	}
	public static List<Cliente> consultarClientesNoSociosBD() {
		List<Cliente> lc=null;
	    Query query = session.createQuery("from Cliente where esSocio = 0");
	    lc = query.list();
		return lc;
	}
	
	//devuelve 0 si el cliente esta en BD y -1 si no esta
	public static Cliente  consultarClienteBD(int dni){
		Cliente c=null;
		try {
			c=(Cliente) session.load(Cliente.class, dni);
		} catch (Exception e) {
			System.err.println("ERROR al consultar cliente");
			e.printStackTrace();
		}
		return c;
	}
	
	public static int  crearClienteBD(Cliente c){
		int res=0;
		try {
		    session.save(c);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al crear cliente");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int modificarClienteBD(Cliente c){
		int res=0;
		try {
		    session.update(c);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al modificar cliente");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int borrarClienteBD(int dni){
		int res=0;
		try {
			Cliente c=(Cliente) session.load(Cliente.class, dni);
			session.delete(c);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al borrar cliente");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	//---------- DEVOLUCIONES -----------
	public static int  devolverArticuloBD(int idVenta,int cantidad,float dinero){
		int res=0;
		Transaction tx = session.beginTransaction();
		
		try {
			//Modificamos la venta devueltos+=cantidad
			Venta v=consultarVentaBD(idVenta);
			v.setDevueltos(v.getDevueltos()+cantidad);
			session.update(v);
			//Creamos el pago negativo
			Pago p=new Pago(-dinero,v.getPago().getCliente(),"Devolucion",v.getUsuario(),1,1);
			session.save(p);
			//Creamos la devolucion
			Devolucion d=new Devolucion(idVenta,cantidad,p.getId());
			session.save(d);
			Articulo a=consultarArticuloBD(v.getArticulo());
			a.setCantidad(a.getCantidad()+cantidad);
			session.update(a);
			tx.commit();
		} catch (Exception e) {
			System.err.println("ERROR al devolver el articulo");
			e.printStackTrace();
			tx.rollback();
			res=-1;
		}
		return res;
	}
	
	
	
	
	//---------- PAGOS -----------
	
	public static int  crearPagoBD(Pago p){
		int res=0;
		try {
		    session.save(p);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al crear pago");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int modificarPagoBD(Pago p){
		int res=0;
		try {
		    session.update(p);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al modificar pago");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int borrarPagoBD(int dni){
		int res=0;
		try {
			Cliente c=(Cliente) session.load(Cliente.class, dni);
			session.delete(c);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al borrar cliente");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	
	public static Pago consultarPagoBD(int id){
		Pago p = null;
		try {
			p=(Pago) session.load(Pago.class, id);
		} catch (Exception e) {
			System.err.println("ERROR al consultar pago");
			e.printStackTrace();
		}
		return p;
	}
	
	public static List<Pago> consultarPagosClienteBD(int dni){
		List<Pago> pagos=null;
	    Query query = session.createQuery("from Pago where cliente = '"+dni+"'");
	    pagos = query.list();
		return pagos;
	}
	private static List<Pago> consultarPagosClientePendientesBD(int id) {
		List<Pago> pagos=null;
	    Query query = session.createQuery("from Pago where cliente = '"+id+"' and liquidado = 0");
	    pagos = query.list();
		return pagos;
	}
	public static List<Pago> consultarPagosBD(){
		List<Pago> pagos=null;
		Criteria crit = session.createCriteria(Pago.class);
	    pagos = crit.list();
		return pagos;
	}
	public static List<Pago> consultarPagosFechasBD(Date fecha_ini,Date fecha_fin){
		List<Pago> pagos=null;
		java.sql.Date ini=new java.sql.Date (fecha_ini.getTime());
		java.sql.Date fin=new java.sql.Date (fecha_fin.getTime());
	    Query query = session.createQuery("from Pago where fecha >= '"+ini.toString()+"' and fecha <= '"+fin.toString()+"'");
	    pagos = query.list();
		return pagos;
	}
	public static List<Pago> consultarPagosClienteFechasBD(int dni,Date fecha_ini,Date fecha_fin){
		List<Pago> pagos=null;
		java.sql.Date ini=new java.sql.Date (fecha_ini.getTime());
		java.sql.Date fin=new java.sql.Date (fecha_fin.getTime());
	    Query query = session.createQuery("from Pago where cliente="+dni+" and fecha >= '"+ini.toString()+"' and fecha <= '"+fin.toString()+"'");
	    pagos = query.list();
		return pagos;
	}
	
	//------- RESERVAS ---------
	//Devuelve una lista con las reservas que hay para un servicio en el dia indicado
	public static Reserva  consultarReservaBD(int id){
		Reserva r=null;
		try {
			r=(Reserva) session.load(Reserva.class, id);
		} catch (Exception e) {
			System.err.println("ERROR al consultar reserva");
			e.printStackTrace();
		}
		return r;
	}
	
	
	public static List<Reserva> consultarReservasFechaBD(int idServicio,Date fecha){
		List<Reserva> lr=null;
		java.sql.Date f=new java.sql.Date (fecha.getTime());
	    Query query = session.createQuery("from Reserva where servicio="+idServicio+" and fechaReserva = '"+f.toString()+"' ORDER BY horaReserva");
	    lr = query.list();
		return lr;
	}
	public static List<Reserva> consultarReservaFechaHoraServicioBD(int idServicio,Date fecha,int hora){
		List<Reserva> lr=null;
		java.sql.Date f=new java.sql.Date (fecha.getTime());
	    Query query = session.createQuery("from Reserva where servicio="+idServicio+" and fechaReserva = '"+f.toString()+"' and horaReserva = '"+hora+"'");
	    lr = query.list();
		return lr;
	}
	
	//------ SERVICIOS ----------
	public static Servicio  consultarServicioBD(int id){
		Servicio s=null;
		try {
			s=(Servicio) session.load(Servicio.class, id);
		} catch (Exception e) {
			System.err.println("ERROR al consultar servicio");
			e.printStackTrace();
		}
		return s;
	}
	public static List<Servicio> consultarServiciosBD(){
		List<Servicio> servicios=null;
		Criteria crit = session.createCriteria(Servicio.class);
	    servicios = crit.list();
		return servicios;
	}
	public static int  crearServicioBD(Servicio s){
		int res=0;
		try {
		    session.save(s);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al crear servicio");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int modificarServicioBD(Servicio s){
		int res=0;
		try {
		    session.update(s);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al crear cliente");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int borrarServicioBD(int id){
		int res=0;
		Servicio s;
		try {
			s=(Servicio) session.load(Servicio.class, id);
		    session.delete(s);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al borrar servicio");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	
	//-------- SESION -------------
	
	public static Sesion  consultarSesionBD(int dni){
		Sesion s=null;
		try {
			System.out.println("consultarSesionBD ---------");
			s=(Sesion) session.load(Sesion.class, dni);
		} catch (Exception e) {
			System.err.println("ERROR al consultar sesion");
			e.printStackTrace();
		}
		return s;
	}
	
	public static int  crearSesionBD(Sesion s){
		int res=0;
		try {
			System.out.println("PTUATTA");
		    session.save(s);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al crear sesion");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int borrarSesionBD(int dni){
		int res=0;
		Sesion s;
		try {
			s=(Sesion) session.load(Sesion.class, dni);
		    session.delete(s);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al borrar sesion");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	
	public static List<Sesion>  consultarSesionesBD(){
		List<Sesion> sesiones=null;
		Criteria crit = session.createCriteria(Sesion.class);
	    sesiones = crit.list();
		return sesiones;
	}
	
	
	// ----- SOCIO ------
	
	//devuelve todos los socios de la BD
	public static List<Socio> consultarSociosBD(){
		List<Socio> ls=null;
		Criteria crit = session.createCriteria(Socio.class);
	    ls = crit.list();
		return ls;
	}
	public static List<Socio> consultarSociosTitularesBD() {
		List<Socio> lc=null;
		
	    Query query = session.createQuery("from Socio where dni=dniTitular ");
	    lc = query.list();
		return lc;
	}
	//devuelve 0 si el socio esta en BD y -1 si no esta
	public static Socio  consultarSocioBD(int dni){
		Socio s=null;
		try {
			s=(Socio) session.load(Socio.class, dni);
		} catch (Exception e) {
			System.err.println("ERROR al consultar socio");
			e.printStackTrace();
		}
		return s;
	}
	private static List<Socio> consultarSociosGrupoBD(int id) {
		List<Socio> ls=null;
	    Query query = session.createQuery("from Socio where dniTitular="+id);
	    ls = query.list();
		return ls;
	}
	public static int  crearSocioBD(Socio s){
		int res=0;
		Transaction tx = session.beginTransaction();
		try {
			
			Cliente c = consultarClienteBD(s.getDni());
			if(c!=null){
				c.setEsSocio(1);
				session.update(c);
			}else{
				System.err.println("ERROR: no existe cliente para ese socio");
				return -1;
			}
		    session.save(s);
		    tx.commit();
		} catch (Exception e) {
			System.err.println("ERROR al crear socio");
			e.printStackTrace();
			res=-1;
			tx.rollback();
		}
		return res;
	}
	public static int modificarSocioBD(Socio s){
		int res=0;
		try {
		    session.update(s);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al modificar socio");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int borrarSocioBD(int dni){
		int res=0;
		Socio s;
		try {
			s=(Socio) session.load(Socio.class, dni);
		    session.delete(s);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al borrar socio");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	
	//------- USUARIO -------
	
	public static Usuario  consultarUsuarioBD(int dni){
		Usuario u=null;
		try {
			u = (Usuario) session.load(Usuario.class, dni);
		} catch (Exception e) {
			System.err.println("ERROR al consultar usuario");
			e.printStackTrace();
		}
		return u;
	}
	public static List<Usuario> consultarUsuariosBD(){
		List<Usuario> usuarios=null;
		Criteria crit = session.createCriteria(Usuario.class);
	    usuarios = crit.list();
		return usuarios;
	}
	
	public static int  crearUsuarioBD(Usuario u){
		int res=0;
		try {
		    session.save(u);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al crear usuario");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int modificarUsuarioBD(Usuario u){
		int res=0;
		try {
		    session.update(u);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al modificar socio");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	public static int borrarUsuarioBD(int dni){
		int res=0;
		Usuario u;
		try {
			u=(Usuario) session.load(Usuario.class, dni);
		    session.delete(u);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al borrar usuario");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}
	
	
	// ------------ VENTAS -------------
	
	public static Venta consultarVentaBD(int id){
		Venta v=null;
		try {
			v = (Venta) session.load(Venta.class, id);
		} catch (Exception e) {
			System.err.println("ERROR al consultar venta");
			e.printStackTrace();
		}
		return v;
	}
	
	//devuelve todas las ventas que tengan el pago
	public static List<Venta> consultarVentasPagoBD(Pago pago){
		List<Venta> ventas=null;

	    Query query = session.createQuery("from Venta where pago="+pago.getId());
	    ventas = query.list();

		return ventas;
	}

	public static List<Venta> consultarVentasBD(){
		List<Venta> ventas=null;
		Criteria crit = session.createCriteria(Venta.class);
	    ventas = crit.list();
		return ventas;
	}
	public static int crearVentaBD(Venta v){
		int res=0;
		try {
		    session.save(v);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al crear venta");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}

	public static int efectuarVentaBD(String[][] m, int dni, int tipoPago,
			int usuario, float totalEuros) {
		int res=0;
		Transaction tx = session.beginTransaction();
		
		try {
			int liquidado=0;
			if(tipoPago==1){//Pago efectivo
				liquidado=1;
			}
			Pago p=new Pago(totalEuros,dni,"Venta",usuario,tipoPago,liquidado);
			session.save(p);
			for (int i = 0; i < m.length; i++) {
				Venta v= new Venta(Integer.parseInt(m[i][0]),Integer.parseInt(m[i][2]),Float.parseFloat(m[i][3]),usuario,p);
				Articulo a=consultarArticuloBD(Integer.parseInt(m[i][0]));
				a.setCantidad(a.getCantidad()-Integer.parseInt(m[i][2]));
				session.update(a);
				session.save(v);
			}
		    tx.commit();
		} catch (Exception e) {
			System.err.println("ERROR al efectuar la venta");
			e.printStackTrace();
			res=-1;
			tx.rollback();
		}
		return res;
	}
	public static int modificarVentaBD(Venta v){
		int res=0;
		try {
		    session.update(v);
		    session.flush();
		} catch (Exception e) {
			System.err.println("ERROR al modificar venta");
			e.printStackTrace();
			res=-1;
		}
		return res;
	}

	public static int crearReserva(int servicio, int usuario, int cliente,
			Date fechaReserva, int horaReserva) {
		int res=0;
		Transaction tx = session.beginTransaction();
		try {
			Servicio s=consultarServicioBD(servicio);
			if(s.getHabilitado()==1){
				List<Reserva> lr =consultarReservaFechaHoraServicioBD(servicio, fechaReserva, horaReserva);
				if (lr.size()==0) {//ESta disponible
					//Creamos el pago
					Cliente c=consultarClienteBD(cliente);
					int tipoPago=0,liquidado=0;
					if(c.getEsSocio()==1){
						tipoPago=2;
						liquidado=0;
					}else{
						tipoPago=1;
						liquidado=1;
					}
					Pago p=new Pago(s.getPrecioHora(),cliente,"Reserva",usuario,tipoPago,liquidado);
					session.save(p);
					Reserva r =new Reserva(servicio,usuario,cliente,fechaReserva,horaReserva,p.getId());
					session.save(r);

				}
				else res=-1;
				
			}
			else{
				res=-1;
			}
			tx.commit();
		} 
		catch (Exception e) {
			System.err.println("ERROR al efectuar la reserva");
			e.printStackTrace();
			res=-1;
			tx.rollback();
		}

		return res;
	}

	public static int anularReservaBD(int reserva) {
		int res=0;
		Transaction tx = session.beginTransaction();
		try {
			
			Reserva r=consultarReservaBD(reserva);
			Servicio s=consultarServicioBD(r.getServicio());
			Cliente c= consultarClienteBD(r.getCliente());
			int tipoPago=1;
			int liquidado=1;
			Date fr =r.getFechaReserva();
			Date fhoy=new Date();
			
			if(fr.compareTo(fhoy)>-1){
				//Si es socio se devuelve el dinero en la mensualidad
				if(c.getEsSocio()==1){
					tipoPago=2;
					liquidado=0;
				}
				//Creamos un pago para devolver el dinero de la reserva
				Pago p =new Pago(-s.getPrecioHora(),r.getCliente(),"Anulacion reserva",r.getUsuario(),tipoPago,liquidado);
				session.save(p);
				//borramos la reserva
				session.delete(r);
			
			}
			else{
				res=-1;
			}
			tx.commit();
		} catch (Exception e) {
			System.err.println("ERROR al anular la reserva");
			e.printStackTrace();
			res=-1;
			tx.rollback();
		}
		return res;
	}



	public static int darBajaSocioBD(int id) {
		int res=0;
		Transaction tx = session.beginTransaction();
		try {
			//liquidamos los pagos
			Socio s =consultarSocioBD(id);
			if(s.getDni()==s.getDniTitular()){
				List<Socio> ls=consultarSociosGrupoBD(id);
				for (int i = 0; i < ls.size(); i++) {
					List<Pago> lp=consultarPagosClientePendientesBD(ls.get(i).getDni());
					for (int j = 0; j < lp.size(); j++) {
						Pago p=lp.get(j);
						p.setLiquidado(1);
						session.update(p);
					}
					Cliente c=consultarClienteBD(ls.get(i).getDni());
					c.setEsSocio(0);
					session.update(c);
					session.delete(ls.get(i));
				}
			}
			else{
				List<Pago> lp=consultarPagosClientePendientesBD(s.getDni());
				for (int j = 0; j < lp.size(); j++) {
					Pago p=lp.get(j);
					p.setLiquidado(1);
					session.update(p);
				}
				Cliente c=consultarClienteBD(id);
				c.setEsSocio(0);
				session.update(c);
				session.delete(s);
			}
			tx.commit();
		} 
		catch (Exception e) {
			System.err.println("ERROR al dar de baja el socio");
			e.printStackTrace();
			res=-1;
			tx.rollback();
		}
		return res;
	}

	public static List<Reserva> consultarReservasServicioBD(int id) {
		List<Reserva> lr=null;
	    Query query = session.createQuery("from Reserva where servicio="+id);
	    lr = query.list();
		return lr;
	}
}
